package recipe.renderer;

import java.io.*;
import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;
import java.lang.Long;

public class Recipe {
	public LinkedList<Task> tasks;
	public String title;
	public String source;

	public Recipe() {
		tasks = new LinkedList<Task>();
		title = "";
		source = "";
	}
	
	public Recipe(Recipe recipe) {
		// create a clone of a recipe
		title = recipe.title;
		source = recipe.source;
		
		//create a copy of the task-array
		tasks = new LinkedList<Task>();
		Map<String, Task> id_to_task = new HashMap<String, Task>();
	    for (Task t : recipe.tasks) {
	    	Task task_copy = new Task(t);
	    	tasks.add(task_copy);
	    	id_to_task.put(t.id, task_copy);
	    }
	    for (Task original_t : recipe.tasks) {
	        // replace pointers to dependencies with pointers to the copies
	    	Task task_copy = id_to_task.get(original_t.id);
	        task_copy.dependencies = new LinkedList<Task>();
	        for (Task d : original_t.dependencies)
	        {
	        	if (d!=null)
	        	task_copy.dependencies.add(id_to_task.get(d.id));
	        }
	    }
	}

	private String joins(String[] stra) {
		String delimiter = " ";
		String joined = "";
		int noOfItems = 0;
		for (String item : stra) {
			if (noOfItems > 0)
				joined += item;
			if (++noOfItems < stra.length)
				joined += delimiter;
		}
		joined=joined.trim();
		return joined;
	}

	public void parse_file(InputStream fstream) {
		try {
			Task ct = null; // current task
			BufferedReader br = new BufferedReader(new InputStreamReader(
					fstream));
			String ln;
			String[] aln;
			Map<String, Task> td = new HashMap<String, Task>();
			while ((ln = br.readLine()) != null) {
				// prepare line for parsing
				ln = ln.trim().replaceAll("[,:\\s]+", ":");
				if (ln.length() == 0)
					continue;
				aln = ln.split("#")[0].split(":");
				if (aln.length == 0)
					continue;
				if (aln[0].equals("title"))
					title = joins(aln);
				if (aln[0].equals("source"))
					source = joins(aln);
				if (aln[0].equals("task")) {
					ct = new Task(joins(aln));
					tasks.add(ct);
					td.put(ct.id, ct);
				}
				if (aln[0].equals("depends_on"))
					for (String cid : aln)
						if ((!cid.equals("depends_on")) && (!cid.equals("")))
							ct.dependencies.add(td.get(cid));
				if (aln[0].equals("duration"))
					tasks.getLast().duration = Long.valueOf(aln[1]);
				if (aln[0].equals("speech"))
					tasks.getLast().speech = joins(aln);
				if (aln[0].equals("query"))
					tasks.getLast().query = joins(aln);
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
 
	public LinkedList<Task> find_available_tasks() {
		LinkedList<Task> ll = new LinkedList<Task>();
		for (Task t : tasks)
			if (t.can_start())
				ll.add(t);
		return ll;
	}

	public LinkedList<Task> find_active_tasks() {
		LinkedList<Task> ll = new LinkedList<Task>();
		for (Task t : tasks)
			if (t.is_active())
				ll.add(t);
		return ll;
	}

	public LinkedList<Task> find_overdue_tasks() {
		LinkedList<Task> ll = new LinkedList<Task>();
		for (Task t : find_active_tasks())
			if (t.is_overdue())
				ll.add(t);
		return ll;
	}
	
	public LinkedList<Task> find_done_tasks() {
		LinkedList<Task> ll = new LinkedList<Task>();
		for (Task t : tasks)
			if (t.completed())
				ll.add(t);
		return ll;
	}
}
